package MyProject.WangYiYun;

// 网易云音乐
// 1.存储所有歌曲(评论数)
// 2.一首歌对应多个评论
// 3.每个评论可以点赞 根据点赞数排序
// 4.歌单 歌单中的歌曲已热度排序(评论数*432 + 喜欢这首歌的人*432 (比例还可以调整) + 发布时间)
// 5.我喜欢的歌

// 实现
// 1.使用Hash存储歌的具体信息 使用String存储ID
// 2.使用Set存储每首歌对应的评论ID
// 3.使用ZSet
// 4.使用Set存储歌曲ID

import redis.clients.jedis.Jedis;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;


public class MyChapter01 {

    private static final int ONE_WEEK_IN_SECONDS = 7 * 86400;
    private static final int VOTE_SCORE = 432;

    private static Song[] songs = new Song[5];

    static {
        for (int i = 0; i < songs.length; i++) {
            songs[i] = new Song("1989" + i, "Taylor Swift" + i);
        }
    }

    public static void main(String[] args) {
        MyChapter01 chapter01 = new MyChapter01();

        Jedis conn = new Jedis("localhost");
        conn.select(10);

//        for (Song song : songs) {
//            chapter01.addSong(conn, song);
//        }

//        chapter01.addComment(conn, "6", "霉霉好棒");
//        chapter01.addComment(conn, "6", "女神加油");

        //少写一个点赞验证的set hhh
        chapter01.good(conn, "6", "1");

        List<Song> list = chapter01.song(conn);
        for (Song song : list) {
            System.out.println(song);
        }
    }

    // 新增歌曲
    private String addSong(Jedis conn, Song song) {
        // 获取歌曲ID
        // ID不存在会创建一个(1) 存在则会自增
        String id = String.valueOf(conn.incr("song:"));

        //将歌曲存入hash中
        String key = "song:" + id;
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("id", id);
        map.put("name", song.getName());
        map.put("singer", song.getSinger());
        map.put("comments", String.valueOf(song.getComments()));
        conn.hmset(key, map);

        //记录热度 初始化成当前时间
        conn.zadd("hot:", now(), key);
        return id;
    }

    // 增加评论
    private void addComment(Jedis conn, String id, String comment) {
        String songKey = "song:" + id;
        //歌曲信息中评论还是加1
        conn.hincrBy(songKey, "comments", 1);
        //增加热度
        conn.zincrby("hot:", VOTE_SCORE, songKey);

        String commentKey = "song:" + id + " comments:";

        //获取评论id
        String commentID = String.valueOf(conn.incr(commentKey));

        commentKey += commentID;

        HashMap<String, String> map = new HashMap<String, String>();
        map.put("id", commentID);
        map.put("comment", comment);
        map.put("time", time());
        map.put("good", "0");

        conn.hmset(commentKey, map);

        //默认给自己点个赞
        conn.zadd("song:" + id + " score:", 1, "comments:" + commentID);
    }

    //点赞
    private void good(Jedis conn, String song, String comment) {
        //增加点赞数(排名)
        conn.zincrby("song:" + song + " score:", 1, "comments:" + comment);
        //hash中记录
        conn.hincrBy("song:" + song + " comments:" + comment, "good", 1);
        //增加歌曲热度
        conn.zincrby("hot:", VOTE_SCORE, "song:" + song);
    }

    //按照热度获取歌曲
    private List<Song> song(Jedis conn) {
        Set<String> set = conn.zrevrange("hot:", 0, -1);
        List<Song> list = new ArrayList<>();
        for (String str : set) {
            list.add(get(conn.hgetAll(str), conn));
        }
        return list;
    }

    private Song get(Map<String, String> map, Jedis conn) {
        Class<Song> clazz = Song.class;
        Song song = null;
        try {
            song = clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        for (Map.Entry<String, String> entry : map.entrySet()) {
            try {
                Field field = clazz.getDeclaredField(entry.getKey());
                if (entry.getKey().equals("id")) {
                    String key = "song:" + entry.getValue() + " score:";
                    Set<String> set = conn.zrevrange(key, 0, -1);
                    List<Comment> list = new ArrayList<>();
                    for (String str : set) {
                        list.add(getComment(conn.hgetAll("song:" + entry.getValue() + " " + str)));
                    }
                    Field commentList = clazz.getDeclaredField("commentList");
                    commentList.setAccessible(true);
                    commentList.set(song, list);
                }
                field.setAccessible(true);
                field.set(song, entry.getValue());
            } catch (IllegalAccessException | NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
        return song;
    }

    private Comment getComment(Map<String, String> map) {
        Class<Comment> clazz = Comment.class;
        Comment comment = null;
        try {
            comment = clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        for (Map.Entry<String, String> entry : map.entrySet()) {
            try {
                Field field = clazz.getDeclaredField(entry.getKey());
                field.setAccessible(true);
                field.set(comment, entry.getValue());
            } catch (IllegalAccessException | NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
        return comment;
    }

    private long now() {
        return System.currentTimeMillis() / 1000;
    }

    private String time() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(new Date());
    }
}
